package com.file.parser;

import com.file.bo.ResponseData;
import com.file.bo.mail.BJRCB;
import com.file.bo.mail.BJRCBTran;
import com.file.constant.ErrorCode;
import com.file.util.JsonUtils;
import com.google.common.base.Strings;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;


import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 丰巢-北京农商行的pdf解析类
 * @author v_wbstlu
 * @date 2023-10-30
 */
@Slf4j
public class BJRCBPdfParser extends BasePdfParser {

	public ResponseData<String> parseBJRCBPdfToJson(String daId, String filePath) {
		log.info("parseBJRCBPdfToJson started, daId:{}", daId);
		String json = null;

		try {
			BJRCB bjrcb = parseBJRCBPdf(filePath);
			json = JsonUtils.convertObjectToJson(bjrcb);
		} catch (Exception e) {
			log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseBJRCBPdfToJson failed", e);
			return new ResponseData<String>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(),
					ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
		}

		log.info("parseBJRCBPdfToJson completed, daId:{}", daId);
		return new ResponseData<String>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
	}

	private BJRCB parseBJRCBPdf(String filePath) {
        BJRCB bjrcb = parseNCJBHeader(filePath);
		List<BJRCBTran> bjrcbTrans = parseBJRCBTrans(filePath);

        bjrcb.setBjrcbTrans(bjrcbTrans);
		return bjrcb;
	}

	private BJRCB parseNCJBHeader(String filePath) {
        BJRCB bjrcb = new BJRCB();
		String pdfHeaderText = parsePdfHeaderText(filePath);

		String accountName = pdfHeaderText.substring(pdfHeaderText.indexOf("账户名称：") + 5, pdfHeaderText.indexOf("客户申请日期：")).trim();//NOSONAR
		String customerApplyDate = pdfHeaderText.substring(pdfHeaderText.indexOf("客户申请日期：") + 7, pdfHeaderText.indexOf("查 询 机 构：")).trim();//NOSONAR
		String queryAgency = pdfHeaderText.substring(pdfHeaderText.indexOf("查 询 机 构：") + 8, pdfHeaderText.indexOf("系统查询日期：")).trim();//NOSONAR
		String systemQueryDate = pdfHeaderText.substring(pdfHeaderText.indexOf("系统查询日期：") + 7, pdfHeaderText.indexOf("收入金额合计：")).trim();//NOSONAR
		String incomeAmtTotal =  pdfHeaderText.substring(pdfHeaderText.indexOf("收入金额合计：") + 7, pdfHeaderText.indexOf("支出金额合计：")).trim();//NOSONAR
		String payAmtTotal =  pdfHeaderText.substring(pdfHeaderText.indexOf("支出金额合计：") + 7, pdfHeaderText.indexOf("查询区间期末余额:")).trim();//NOSONAR
		String queryIntervalBalance =  pdfHeaderText.substring(pdfHeaderText.indexOf("查询区间期末余额:") + 9, pdfHeaderText.indexOf("交易明细合计：")).trim();//NOSONAR
		String transactionDetailsTotal =  pdfHeaderText.substring(pdfHeaderText.indexOf("交易明细合计：") + 7, pdfHeaderText.indexOf("账号：")).trim();//NOSONAR
		String accountNo =  pdfHeaderText.substring(pdfHeaderText.indexOf("账号：") + 3, pdfHeaderText.indexOf("查询条件：")).trim();//NOSONAR
		String currency =  pdfHeaderText.substring(pdfHeaderText.indexOf("币种：") + 3, pdfHeaderText.indexOf("（2）交易起止日期：")).trim();//NOSONAR
		String transactionDate =  pdfHeaderText.substring(pdfHeaderText.indexOf("交易起止日期：") + 7, pdfHeaderText.indexOf("（3）交易金额：")).trim();//NOSONAR
		String transactionAmount =  pdfHeaderText.substring(pdfHeaderText.indexOf("交易金额：") + 5, pdfHeaderText.indexOf("（4）交易类型：")).trim();//NOSONAR
		String tranType =  pdfHeaderText.substring(pdfHeaderText.indexOf("交易类型：") + 5, pdfHeaderText.indexOf("交易时间 ")).trim();//NOSONAR
		String deliverDate =  pdfHeaderText.substring(pdfHeaderText.indexOf("交付日期：") + 5, pdfHeaderText.indexOf("查询索引号：")).trim();//NOSONAR
		String queryIndexNumber =  pdfHeaderText.substring(pdfHeaderText.indexOf("查询索引号：") + 6, pdfHeaderText.indexOf("第1页")).trim();//NOSONAR

        bjrcb.setAccountName(accountName);
        bjrcb.setCustomerApplyDate(customerApplyDate);
        bjrcb.setQueryAgency(queryAgency);
        bjrcb.setSystemQueryDate(systemQueryDate);
        bjrcb.setIncomeAmtTotal(incomeAmtTotal);
        bjrcb.setPayAmtTotal(payAmtTotal);
        bjrcb.setQueryIntervalBalance(queryIntervalBalance);
        bjrcb.setTransactionDetailsTotal(transactionDetailsTotal);
        bjrcb.setAccountNo(accountNo);
        bjrcb.setCurrency(currency);
        bjrcb.setTransactionDate(transactionDate);
        bjrcb.setTransactionAmount(transactionAmount);
        bjrcb.setTranType(tranType);
        bjrcb.setDeliverDate(deliverDate);
        bjrcb.setQueryIndexNumber(queryIndexNumber);

		return bjrcb;
	}

	private List<BJRCBTran> parseBJRCBTrans(String filePath) {
		List<BJRCBTran> bjrcbTrans = new ArrayList<>();

		String transText = getPdfTextByStripper(filePath);
		if (Strings.isNullOrEmpty(transText)) {
			return bjrcbTrans;
		}

		List<List<String>> tranFieldsList = parseTransTextToTranFieldsList(transText);

        // 交易时间
        String transactionTime = "";
        Boolean transactionTimeStatus = false;
        // 交易流水号
        String tranSerialNo = "";
        Boolean tranSerialNoStatus = false;
        // 交易金额
        String transactionAmount = "";
        Boolean transactionAmountStatus = false;
        // 账户余额
        String balance = "";
        // 摘要
        String summary = "";
        // 附言
        String postscript = "";
        Boolean postscriptStatus = false;
        // 对方户名
        String counterPartyAccountName = "";
        Boolean counterPartyAccountNameStatus = false;
        // 对方账号
        String counterPartyAccountNumber = "";
        Boolean counterPartyAccountNumberStatus = false;
        // 对方银行名称
        String counterPartyBankName = "";
        Boolean counterPartyBankNameStatus = false;

		for (int i = 0; i < tranFieldsList.size(); i++) {
            List<String> strings = tranFieldsList.get(i);
			if (StringUtils.isBlank(strings.get(0)) || strings.get(0).contains("交付日期：")  || strings.get(0).contains("交易时间")  || strings.get(0).contains("北京农商银行客户交易信息回单") ||  i+1 == tranFieldsList.size()) {
                continue;
            }

			if (strings.get(0).contains("==========================")) {
			    // 记录的最后一行后面是等号
			    break;
            }
            // 下一行的数据
            List<String> nextStrings = tranFieldsList.get(i + 1);

            String[] contents = strings.get(0).split(" ");

            // 交易时间
            if (Boolean.FALSE.equals(transactionTimeStatus) && (Boolean.TRUE.equals(isValidDate(contents[0]) || Boolean.TRUE.equals(isValidTimeFormat(contents[0]))))) {
                if (Boolean.FALSE.equals(isValidTimeFormat(nextStrings.get(0).split(" ")[0]))) {
                    transactionTime += contents[0];
                    transactionTimeStatus = true;
                    continue;
                } else {
                    transactionTime += contents[0] + " ";
                }
            }

            // 交易流水号
            if (Boolean.TRUE.equals(transactionTimeStatus) && Boolean.FALSE.equals(tranSerialNoStatus)) {
                tranSerialNo += contents[0];
                if (nextStrings.get(0).split(" ")[0].startsWith("+") || nextStrings.get(0).split(" ")[0].startsWith("-") ) {
                    tranSerialNoStatus = true;
                    continue;
                }
            }

            // 交易金额
            if (Boolean.TRUE.equals(tranSerialNoStatus) && Boolean.FALSE.equals(transactionAmountStatus)) {
                if (contents.length == 3) {
                    transactionAmount += contents[0];
                    balance += contents[1];
                    summary += contents[2];
                }
                if (contents.length == 4) {
                    transactionAmount += contents[0];
                    balance += contents[1];
                    summary += contents[2];
                    if (contents[3].length() == 2) {
                        postscript += contents[3];
                        postscriptStatus = true;
                    } else {
                        // 附言为空， 对方户名不为空
                        counterPartyAccountName += contents[3];
                        postscriptStatus = true;
                        counterPartyAccountNameStatus = true;
                    }

                }
                if (contents.length == 5) {
                    transactionAmount += contents[0];
                    balance += contents[1];
                    summary += contents[2];
                    postscript += contents[3];
                    postscriptStatus = true;
                    counterPartyAccountName += contents[4];
                    counterPartyAccountNameStatus = true;
                }
                if (contents.length == 6) {
                    transactionAmount += contents[0];
                    balance += contents[1];
                    summary += contents[2];
                    postscript += contents[3];
                    postscriptStatus = true;
                    counterPartyAccountName += contents[4];
                    counterPartyAccountNameStatus = true;
                    counterPartyAccountNumber += contents[5];
                    counterPartyAccountNumberStatus = true;
                }
                if (contents.length == 7) {
                    transactionAmount += contents[0];
                    balance += contents[1];
                    summary += contents[2];
                    postscript += contents[3];
                    postscriptStatus = true;
                    counterPartyAccountName += contents[4];
                    counterPartyAccountNameStatus = true;
                    counterPartyAccountNumber += contents[5];
                    counterPartyAccountNumberStatus = true;
                    counterPartyBankName += contents[6];
                }
                transactionAmountStatus = true;
            }

            if (transactionAmountStatus && !postscriptStatus && contents[0].length() == 2) {
                postscript += contents[0];
                if (nextStrings.get(0).split(" ")[0].length() != 2) {
                    postscriptStatus = true;
                    continue;
                }
            }

            if (postscriptStatus && !counterPartyAccountNameStatus && contents.length < 4) {
                counterPartyAccountName += contents[0];
                if (StringUtils.isNotEmpty(nextStrings.get(0)) && checkIfNumber(nextStrings.get(0).split(" ")[0].replaceAll("\\*", ""))) {
                    counterPartyAccountNameStatus = true;
                    continue;
                }
            }

            if (counterPartyAccountNameStatus && !counterPartyAccountNumberStatus && contents.length < 4) {
                counterPartyAccountNumber += contents[0];
                if (!checkIfNumber(nextStrings.get(0).split(" ")[0].replaceAll("\\*", ""))) {
                    counterPartyAccountNumberStatus = true;
                    continue;
                }
            }

            if (counterPartyAccountNumberStatus && contents.length < 4) {
                counterPartyBankName += contents[0];
            }

            // 如果下一条记录是日期或者很多等号就说明这行解析完成
            if (Boolean.TRUE.equals(isValidDate(nextStrings.get(0).split(" ")[0])) || nextStrings.get(0).contains("==========================") || nextStrings.get(0).contains("北京农商银行客户交易信息回单")) {
                counterPartyBankNameStatus = true;
            }


            // 解析完成
            if (counterPartyBankNameStatus) {
                BJRCBTran bjrcbTran = new BJRCBTran();
                bjrcbTran.setTransactionTime(transactionTime);
                bjrcbTran.setTranSerialNo(tranSerialNo);
                bjrcbTran.setTransactionAmount(transactionAmount);
                bjrcbTran.setBalance(balance);
                bjrcbTran.setSummary(summary);
                bjrcbTran.setPostscript(postscript);
                bjrcbTran.setCounterPartyAccountName(counterPartyAccountName);
                bjrcbTran.setCounterPartyAccountNumber(counterPartyAccountNumber);
                bjrcbTran.setCounterPartyBankName(counterPartyBankName);
                bjrcbTrans.add(bjrcbTran);
                // 交易时间
                transactionTime = "";
                transactionTimeStatus = false;
                // 交易流水号
                tranSerialNo = "";
                tranSerialNoStatus = false;
                // 交易金额
                transactionAmount = "";
                transactionAmountStatus = false;
                // 账户余额
                balance = "";
                // 摘要
                summary = "";
                // 附言
                postscript = "";
                postscriptStatus = false;
                // 对方户名
                counterPartyAccountName = "";
                counterPartyAccountNameStatus = false;
                // 对方账号
                counterPartyAccountNumber = "";
                counterPartyAccountNumberStatus = false;
                // 对方银行名称
                counterPartyBankName = "";
                counterPartyBankNameStatus = false;

            }

		}
		return bjrcbTrans;
	}

    /**
     * 校验字符串是否是yyyy/MM/dd,yyyy/M/dd,yyyy/MM/d,yyyy/M/d格式
     * @param dateString
     * @return
     */
    public static boolean isValidDate(String dateString) {
        if (dateString == null) {
            return false;
        }
        String[] dateArr = dateString.split("/");
        if (dateArr.length != 3) {
            return false;
        }
        if (checkIfNumber(dateArr[0]) && checkIfNumber(dateArr[1]) && checkIfNumber(dateArr[2])) {
            return true;
        }
        return false;
    }

    /**
     * 校验字符串是否是hh:mm:ss的格式
     * @param time
     * @return
     */
    public static boolean isValidTimeFormat(String time) {
        if (time == null) {
            return false;
        }
        Pattern TIME_PATTERN = Pattern.compile("^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$");
        return TIME_PATTERN.matcher(time).matches();
    }

    /**
     * 校验字符串是否是数字
     * @param str
     * @return
     */
    private static boolean checkIfNumber(String str){
        try{
            double num = Double.parseDouble(str); //将字符串转换成double类型  //NOSONAR
            return true;
        }catch (Exception e){
            return false;
        }
    }

	public static void main(String[] args) {
		BJRCBPdfParser bjrcbPdfParser = new BJRCBPdfParser();
		BJRCB bjrcb = bjrcbPdfParser.parseBJRCBPdf("D:\\data\\file\\北京农商行\\zd20kldt1780483003235471360.pdf");
		String json = JsonUtils.convertObjectToJson(bjrcb);
		log.info(json);
	}

}
